home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 10 / des.zip / DESMODES.C < prev    next >
Text File  |  1989-08-27  |  9KB  |  367 lines

  1. /*
  2.  *    desmodes.c
  3.  *
  4.  *    Encrypt and Decrypt Bytes using the DES algorithm
  5.  *
  6.  *    Version 1.2, January 29, 1985 By R. W. Outerbridge
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <fcntl.h>
  11.  
  12. #define    toascii(a)    ((a) & 0177)
  13.  
  14. #define    EN    0
  15. #define    DE    1
  16. #define CKS    2
  17. #define MODES    6    /* three modes times two cases  */
  18. #define BUFFER    1024
  19.  
  20. typedef char    BYTE;   /* BYTE = (vax) ? int : char    */
  21.         
  22. /* cryptographic declarations   */
  23.  
  24. void    copy8(), xor8(), getkey();
  25.  
  26. BYTE    Block[8], Link[8], Temp[8], IV[8];
  27.  
  28. BYTE    DFLTKY[8] = { 1,35,69,103,137,171,205,239 };
  29.  
  30.     /* DO NOT ALTER! => 0x0123456789abcdef <=       */
  31.  
  32. extern void    desinit(), kinit(), des();
  33.  
  34. /* I/O declarations     */
  35.  
  36. void    ruderr(), put8(), vraiput(), initio();
  37. int    IOedf, End, Once;
  38. BYTE    Last[8];
  39.  
  40. int    Ecb(), Cbc(), Cks();
  41.  
  42. struct    modes   {
  43.     char    *name;
  44.         int    (*func)();
  45. };
  46.  
  47. struct    modes    ModsOp[MODES] = {    /* Upper and Lower case */
  48.         { "ecb", Ecb },
  49.         { "ECB", Ecb },
  50.         { "cbc", Cbc },
  51.         { "CBC", Cbc },
  52.         { "cks", Cks },
  53.         { "CKS", Cks }
  54. };
  55.  
  56. char    inbuf[BUFFER], outbuf[BUFFER];
  57.  
  58.  
  59. main(argc, argv)
  60. int    argc;
  61. char    **argv;
  62. {
  63.     int    (*xeqtr)();
  64.         int    step, ende, edio, ok, i;
  65.         BYTE    kv[8];
  66.  
  67.     setmode(0, O_BINARY);
  68.     setmode(1, O_BINARY);
  69.  
  70.     setvbuf(stdin,  inbuf,  _IOFBF, BUFFER);
  71.     setvbuf(stdout, outbuf, _IOFBF, BUFFER);
  72.  
  73.         argv++;
  74.     argc--;
  75.  
  76.         if (argc > 3 || argc < 2)
  77.         ruderr();
  78.         else
  79.         desinit();
  80.  
  81.         for (step = 0; argc > 0; step++)  {
  82.                 switch (step)  {
  83.                 case 0:    /* set en/de and/or default mode        */
  84.                     if (*argv[0] == '+' || *argv[0] == '-')  {
  85.                                 ende = (*argv[0] == '+') ? EN : DE;
  86.                                 *argv[0]++ = NULL;
  87.  
  88.                                 if (*argv[0] == NULL)  {
  89.                                         xeqtr = Ecb;    /* default mode */
  90.                                         edio = ende;
  91.                                         argv++;
  92.                     argc--;
  93.                                         break;
  94.                                 }
  95.                         } else
  96.                 ende = EN;
  97.  
  98.                         for (i = ok = 0; i < MODES && !ok; i++)  {
  99.                                 if (strcmp(argv[0], ModsOp[i].name) == 0)  {
  100.                                         xeqtr = ModsOp[i].func;
  101.                                         ok = 1;
  102.                                 }
  103.                         }
  104.  
  105.                         if (!ok)  {
  106.                                 fprintf(stderr,
  107.                     "des: unknown mode >%s<\n", argv[0]);
  108.                                 ruderr();
  109.                         }
  110.  
  111.                         while (*argv[0])
  112.                 *argv[0]++ = NULL;
  113.  
  114.                         argv++;
  115.             argc--;
  116.  
  117.                         /* set appropriate IO modes     */
  118.  
  119.                         if (xeqtr == Cks)
  120.                 edio = CKS;
  121.                         else
  122.                 edio = ende;
  123.  
  124.             /* falling through....  */
  125.  
  126.                 case 1: /* get the key and IV, if needed and present    */
  127.             if (strcmp(argv[0], "#") == 0)  {
  128.                                 copy8(DFLTKY, kv);
  129.                                 *argv[0] = NULL;
  130.                         } else
  131.                 getkey(argv[0], kv);
  132.  
  133.                         argv++;
  134.             argc--;
  135.                         
  136.                         /* if nothing left, but an IV needed, use the key */
  137.  
  138.                         if (argc == 0)  {
  139.                                 if (xeqtr != Ecb)
  140.                     copy8(kv, IV);
  141.                                 break;
  142.                         } else if (xeqtr == Ecb)  {
  143.                                 fprintf(stderr, "des: ivec ignored\n");
  144.  
  145.                                 while (*argv[0])
  146.                     *argv[0]++ = NULL;
  147.  
  148.                                 argv++;
  149.                 argc--;
  150.                                 break;
  151.                         } else
  152.                 getkey(argv[0], IV);
  153.  
  154.                         argv++;
  155.             argc--;
  156.                         break;
  157.                 default:
  158.                         fprintf(stderr, "des: Program error, call Guru!\n");
  159.                         exit(1);
  160.                 }
  161.     }
  162.  
  163.         kinit(kv, ende);
  164.         initio(edio);
  165.         (*xeqtr)(ende);        /* ta-da! Take it away xeqtr!  */
  166.  
  167.         exit(0);
  168. }
  169.  
  170. void ruderr()
  171. {
  172.     fprintf(stderr, "Usage: des (+|-)([ecb]|<cbc|cks>) key1 <ivec>\n");
  173.         exit(1);
  174. }
  175.  
  176. Cbc(e_d)        /* Cipher Block Chaining                */
  177. int    e_d;    /* Ciphertext errors are self-healing.  */
  178. {
  179.         copy8(IV, Link);
  180.  
  181.         while (get8(Block) != EOF)  {
  182.                 if (e_d == DE)  {
  183.                         des(Block, Temp);
  184.                         xor8(Temp, Link);
  185.                         copy8(Block, Link);
  186.                         put8(Temp);
  187.                 } else  {
  188.                         xor8(Block, Link);
  189.                         des(Block, Link);
  190.                         put8(Link);
  191.                 }
  192.         }
  193. }
  194.  
  195. Cks(dummy)      /* CBC authentication checksum generator        */
  196. int    dummy;    /* The banks use this for verifications.        */
  197. {
  198.         int    i, j, k;
  199.         long    count = 0L;
  200.  
  201.         copy8(IV, Link);
  202.  
  203.         while (get8(Block) != EOF)  {
  204.                 xor8(Block, Link);
  205.                 des(Block, Link);
  206.                 count++;
  207.         }
  208.  
  209.         fprintf(stdout, ": %0ld bytes\t: ", count << 3);
  210.  
  211.         for (i = j = 0; i < 2; i++)  {
  212.                 for (k = 0; k < 4; k++, j++)
  213.                         fprintf(stdout, "%02x", Link[j] & 0377);
  214.  
  215.                 putc(' ', stdout);
  216.     }
  217.  
  218.         fprintf(stdout, ":\n");
  219. }
  220.  
  221. Ecb(dummy)      /* Electronic Code Book : simple substitution   */
  222. int    dummy;    /* Yawn.        For static data and random access.      */
  223. {
  224.         while (get8(Block) != EOF)  {
  225.                 des(Block, Block);
  226.                 put8(Block);
  227.         }
  228. }
  229.  
  230. void copy8(from, to)
  231. register BYTE    *from, *to;
  232. {
  233.         register BYTE    *ep;
  234.  
  235.         ep = &to[8];
  236.  
  237.         while (to < ep)
  238.         *to++ = *from++;
  239. }
  240.  
  241. void xor8(to, with)
  242. register BYTE    *to, *with;
  243. {
  244.         register BYTE    *ep;
  245.  
  246.         ep = &to[8];
  247.  
  248.         while (to < ep)
  249.         *to++ ^= *with++;
  250. }
  251.  
  252. void put8(block)
  253. register BYTE    *block;
  254. {
  255.         if (IOedf == DE)
  256.         copy8(block, Last);
  257.         else
  258.         vraiput(block, &block[8]);
  259. }
  260.  
  261. get8(input)     /* KLUDGE: incomplete blocks handled sleazily   */
  262. register BYTE    *input;
  263. {
  264.         register int    i, j;
  265.  
  266.         if (End == 1)
  267.         return(EOF);    /* no more input        */
  268.  
  269.         for (i = 0; i < 8 && ((j = getc(stdin)) != EOF); i++)
  270.         *input++ = j;
  271.  
  272.         if (IOedf == DE)  {       /* DECRYPTION   */
  273.  
  274.         /* complete block?      pending output? */
  275.  
  276.                 if (i == 8 && (Once > 0))
  277.             vraiput(Last, &Last[8]);
  278.                 else if (j == EOF)  {
  279.                         End = 1;
  280.  
  281.                         if (Once > 0)  {
  282.  
  283.                                 /* incomplete block means no nulls      */
  284.  
  285.                                 if (i != 0)
  286.                     i = 0;
  287.                                 else  {
  288.                                         i = Last[7] & 0377;
  289.                                         if (i > 8)
  290.                         i = 0;        /* huh? */
  291.                                 }
  292.  
  293.                                 vraiput(Last, &Last[8 - i]);
  294.             }
  295.  
  296.                         return(EOF);
  297.         }
  298.     } else if (j == EOF)  {     /* ENCRYPTION   */
  299.         End = 1;
  300.  
  301.                 if (i == 0 && (IOedf == EN || (Once > 0)))  {
  302.  
  303.                         /* if no padding to do, print a kludge  */
  304.  
  305.                         if (IOedf == EN && (Once > 0))
  306.                 putc('0', stdout);
  307.  
  308.                         return(EOF);
  309.                 }
  310.  
  311.                 for (j = i; j < 7; j++)
  312.             *input++ = NULL;
  313.  
  314.                 *input = 8 - i;
  315.     }
  316.  
  317.         Once = 1;
  318.         return(0);
  319. }
  320.  
  321. void vraiput(cp, ep)
  322. register BYTE    *cp, *ep;
  323. {
  324.         while (cp < ep)
  325.         putc((char)*cp++, stdout);
  326. }
  327.  
  328. void initio(edf)    /* use this as a hook on systems without UNIX   */
  329. int    edf;
  330. {
  331.         IOedf = edf;
  332.         End = Once = 0;
  333. }
  334.  
  335. void getkey(aptr, kptr)
  336. register char    *aptr;
  337. register BYTE    *kptr;
  338. {
  339.         register BYTE    *store;
  340.         register int    i, first;
  341.         BYTE        hold[8];
  342.  
  343.         store = kptr;
  344.         first = 1;
  345.  
  346.         kinit(DFLTKY, EN);
  347.         copy8(DFLTKY, hold);
  348.  
  349.         while (*aptr || first)  {
  350.                 kptr = store;
  351.  
  352.                 for (i = 0; i < 8 && (*aptr != NULL); i++)  {
  353.                         *kptr++ = toascii(*aptr);
  354.                         *aptr++ = NULL;
  355.                 }
  356.  
  357.                 while (i++ < 8)
  358.             *kptr++ = NULL;
  359.  
  360.                 xor8(store, hold);
  361.                 des(store, hold);
  362.                 first = 0;
  363.     }
  364.  
  365.         copy8(hold, store); 
  366. }
  367.